package com.rpc.utils;
import java.io.File;
import java.io.FileFilter;
import java.lang.annotation.Annotation;
import java.net.JarURLConnection;
import java.net.URL;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
/**
 * @Auther: pengjf
 * @Date: 2018-08-15 14:02
 * @Description:
 */
public class AnoncationUtils {
    /***
     *
     * @param packName 指定扫描包
     * @param anoncationClass 只扫描指定注解的类
     * @throws Exception 异常
     */
    public static   Map<String,Object> scanAnoncationClass(String packName,Class<? extends Annotation> anoncationClass) throws Exception {

        ClassLoader loader=AnoncationUtils.class.getClassLoader();
        //将包名com.learn.test 替换成com/learn/test
        Enumeration<URL> urls=loader.getResources(packName.replace(".", "/"));
        Map<String,Object> map=new HashMap<String, Object>();
        while(urls.hasMoreElements()){
            URL url=urls.nextElement();//找到指定包所在位置类型（jar包中还是当前目录中文件目录）
             if(url!=null && null!=url.getProtocol() && !"".equals(url.getProtocol())){//url有效的时候
                if(url.getProtocol().equals("jar")){//url是jar的类型处理逻辑
                    dealForjar(url,packName,loader,anoncationClass,map);
                }else if(url.getProtocol().equals("file")){//url是file类型的处理逻辑
                    dealForFile(url,packName,url.getPath(),loader,anoncationClass,map);
                }

            }
        }
        return map;


    }

    /**
     *
     * @param url  file的url
     * @param packName 包名
     * @param path 路径
     * @param loader 类加载器
     * @throws Exception
     */
    private static void dealForFile(URL url,String packName, String path, ClassLoader loader,Class<? extends Annotation> anoncationClass,Map<String,Object> map) throws Exception {

        File[] files=doFilter(path);//主要.class文件或者目录
         for(File file:files){
            if(file.isFile()){//读取文件
                //获取类权限名
                String className=packName+"."+file.getName().replace(".class", "");
                 Class<?> clazz=loader.loadClass(className);
                if(clazz.isAnnotationPresent(anoncationClass)){
                    map.put(clazz.getInterfaces()[0].getName(), clazz);

                }

            }

        }


    }
    /****
     * 指定目录下文件类型进行过滤
     * **/
    private static File[] doFilter(String path){
        return new File(path).listFiles(new FileFilter() {
            @Override
            public boolean accept(File file) {
                return ((file.isFile() &&  file.getName().endsWith(".class"))||file.isDirectory() );
            }
        });
    }
    private  static void dealForjar(URL url,String packName,ClassLoader loader,Class<? extends Annotation> anoncationClass,Map<String,Object> map) throws Exception{
        JarURLConnection jarUrl=(JarURLConnection) url.openConnection();
        JarFile jarFile=jarUrl.getJarFile();
        Enumeration<JarEntry>  jarEntrys=jarFile.entries();
        while(jarEntrys.hasMoreElements()){
            JarEntry jarEntry=jarEntrys.nextElement();
             String name=jarEntry.getName();
            if(name.endsWith("Impl.class")){
                //遍历所有的包内的class文件
                String prefix=jarEntry.getName().substring(0,jarEntry.getName().lastIndexOf('/'));
                if(prefix.replace('/', '.').startsWith(packName)){
                    Class<?> clazz=loader.loadClass(name.replace("/", ".").replace(".class", ""));
                    if(null!=clazz.getAnnotation(anoncationClass)){
                         map.put(clazz.getInterfaces()[0].getName(), clazz);
                    }


                }
            }

        }

    }


}
